function varargout = TLAddfileDlg(action,varargin)

% TL_ADDFILE_DLG manages the user interface for TargetLink Addfile block
%
% SYNTAX dlgInfo = TLAddfileDlg('GetDlgInfo');
%   gets dialog info of TargetLink Addfile block
%
%   INPUT ARGUMENTS
%   -/-      
%
%   OUTPUT ARGUMENTS
%   dlgInfo     dialog information contains pageNames etc.
%
% SYNTAX [sheetDims, ctrlPos] = TLAddfileDlg('CtrlPositions', pageName, commonGeom, dlgInfo, sheetDims);
%   calculates the control positions of all controls of dialog page: <pageName>
%
%   INPUT ARGUMENTS
%   pageName        name of current page
%   commonGeom      common geometry data
%   dlgInfo         dialog information contains pageNames etc.
%   sheetDims       dimension of sheet
%
%   OUTPUT ARGUMENTS
%   sheetDims       modified dimension of sheet
%   ctrlPos         positions of controls
%
% SYNTAX dlgdata = TLAddfileDlg('Create', pageName, dlgfig, dlgdata);
%   creates all controls of dialog page: <pageName>
%
%   INPUT ARGUMENTS
%   pageName        name of current page
%   dlgfig          figure handle
%   dlgdata         dialog data
%
%   OUTPUT ARGUMENTS
%   dlgdata         modified dialog data
%
% SYNTAX [dlgdata,bModified] = TLAddfileDlg('Manage', pageName, dlgfig, dlgdata, pageAction);
%   manages all actions of dialog page: <pageName>
%
%   INPUT ARGUMENTS
%   pageName        name of current page
%   dlgfig          figure handle
%   dlgdata         dialog data
%   pageAction      modified control of current page
%
%   OUTPUT ARGUMENTS
%   dlgdata         modified dialog data
%   bModified       flag = 1, if dialog data are modified, =0 otherwise
%
% SYNTAX dlgdata = TLAddfileDlg('Update', dlgfig, dlgdata, pageNum);
%   updates all controls of dialog page: <pageNum>
%
%   INPUT ARGUMENTS
%   dlgfig          figure handle
%   dlgdata         dialog data
%   pageNum         number of current page
%
%   OUTPUT ARGUMENTS
%   dlgdata         modified dialog data
%
% SYNTAX TLAddfileDlg('Apply', dlgfig, dlgdata);
%   writes current blockdata to block and DD
%
%   INPUT ARGUMENTS
%   dlgfig      handle for dialog figure
%   dlgdata     dialog data
%
%   OUTPUT ARGUMENTS
%   - / -


% Author(s): D. Andoleit, T. Pietzsch
% $RCSfile: TLAddfileDlg.m $
% $ProjectName: e:/ARC/Components/HostSW/SimulinkBlocksets/TLBlocksets/CommonBlockset/CommonBlockset_UtilityBlocksUI/Sources/MSrc/project.pj $
% $Revision: 1.20 $
% $Date: 2011/08/30 12:41:18MESZ $
%
% Copyright ?2011 dSPACE GmbH. All rights reserved.


switch action

    case 'GetDlgInfo'
        hBlock = varargin{1};
        dlgInfo = tl_get_dlginfodefaults('tlutil');
        titleName = 'Addfile';
        pathinfo = tl_pathinfo(hBlock);
        dlgInfo.title = sprintf('TargetLink %s: %s', titleName, pathinfo.shortDisplayName);
        dlgInfo.bViewCode = 0;
        dlgInfo.pageNames = {
            'Options'; ...
            'Documentation'};
        varargout{1} = dlgInfo;
        varargout{2} = get_tlcg_data(hBlock);

    case 'CtrlPositions'
        pageName     = varargin{1};
        commonGeom   = varargin{2};
        sheetDims    = varargin{4};

        switch pageName
            case 'Options'
                [sheetDims,ctrlPos] = FcnOptionsCtrlPositions(commonGeom);
            case 'Documentation'
                bTblBlock = 0;
                bCodeComment = 1;
                [sheetDims,ctrlPos] = ...
                    TLManageDocCtrls('ctrlpos',commonGeom,sheetDims,bCodeComment,bTblBlock);
        end
        varargout{1} = sheetDims;
        varargout{2} = ctrlPos;

    case 'Create'
        pageName = varargin{1};
        dlgfig   = varargin{2};
        dlgdata  = varargin{3};
        pageNum  = strmatch(pageName,dlgdata.pageNames,'exact');
        switch pageName
            case 'Options'
                dlgdata = FcnCreateOptionsPage(pageNum,dlgfig,dlgdata);
            case 'Documentation'
                dlgdata = ...
                    TLManageDocCtrls('create',pageNum,dlgfig,dlgdata);
        end
        dlgdata.pageData{pageNum}.ctrlPos = [];
        varargout{1} = dlgdata;

    case 'Manage',
        pageName   = varargin{1};
        dlgfig     = varargin{2};
        dlgdata    = varargin{3};
        pageAction = varargin{4};
        pageNum    = strmatch(pageName,dlgdata.pageNames,'exact');

        switch pageName
            case 'Options'
                [dlgdata, bModified] = FcnManageOptionsPage(pageNum,dlgdata,pageAction);
            case 'Documentation'
                [dlgdata,bModified] = ...
                    TLManageDocCtrls('callback',pageNum,dlgfig,dlgdata,pageAction);
        end
        varargout{1} = dlgdata;
        varargout{2} = bModified;

    case 'ManageSystemIcons',
        dlgfig     = varargin{1};
        dlgdata    = varargin{2};
        pageAction = varargin{3};
        [dlgdata, bModified] = FcnManageSystemIcons(dlgfig,dlgdata,pageAction);
        varargout{1} = dlgdata;
        varargout{2} = bModified;

    case 'Update'
        dlgfig   = varargin{1};
        dlgdata  = varargin{2};
        pageNum  = varargin{3};
        pageName = dlgdata.pageNames{pageNum};
        switch pageName
            case 'Options'
                dlgdata = FcnUpdateOptionsPage(pageNum, dlgfig, dlgdata);

            case 'Documentation'
                TLManageDocCtrls('update', pageNum, dlgfig, dlgdata);
        end
        varargout{1} = dlgdata;

    case 'Apply'
        dlgdata  = varargin{2};
        bClose   = varargin{3};
        [dlgdata, bClose] = tl_apply_blockdata(dlgdata, bClose);
        varargout{1} = dlgdata;
        varargout{2} = bClose;

    otherwise
        error(['Invalid action ''' action '''']);

end


%-----------------------------------------------------------------------------------------
% FcnManageSystemIcons manage actions of toolbar icons
%
% INPUT ARGUMENTS
%   dlgfig      handle for dialog figure
%   dlgdata     dialog data
%   action      action at one control of current page
%
% OUTPUT ARGUMENTS
%   dlgdata     modified dialog data
%   bModified   flag = 1, if dialog data are modified, =0 otherwise
%-----------------------------------------------------------------------------------------
function [dlgdata, bModified] = FcnManageSystemIcons(dlgfig, dlgdata, action) %#ok

bModified = false;
switch action
    case 'EditCode'
        data = dlgdata.data;
        if ~isempty(data.codefile)
            % look on MATLAB's search path
            if exist(data.codefile, 'file'),
                codeedit(data.codefile);
            else
                % now look on user-defined paths
                incPath = dsdd('GetTargetLinkIncludeFileSearchPath','/Config');
                srcPath = dsdd('GetTargetLinkSourceFileSearchPath','/Config');
                usrPath = {};
                codefile = '';
                if ~isempty(incPath)
                    usrPath = strread(incPath,'%s','delimiter',';');
                end
                if ~isempty(srcPath)
                    usrPath = [usrPath; strread(srcPath,'%s','delimiter',';')];
                end
                for i=1:length(usrPath)
                    codefile = fullfile(usrPath{i},data.codefile);
                    if exist(codefile,'file') == 2
                        codeedit(codefile);
                        break;
                    else
                        codefile = '';
                    end
                end
                if isempty(codefile)
                    ds_msgbox('Message',{ ...
                        'The file'  ...
                        ['  ' data.codefile] ...
                        'could neither be found on the MATLAB search path,' ...
                        'nor on any user-defined path.' }, ...
                        'Title','File not found', ...
                        'Style','Error');
                end
            end
        end

    case 'ViewCode'
        tl_create_links_to_model('ShowCodeViewFile',dlgdata.model);

    otherwise
        error('Invalid callback');

end % switch(action)


%-------------------------------------------------------------------------------
% FcnOptionsCtrlPosition calculates positions of blockspecific controls of option page.
%   Positions are calculated from the bottom left of the fig to avoid
%   dependencies on figure size.
%
% INPUT ARGUMENTS
%   commonGeom      common geometries like text height, ...
%   sheetDims       total sheetDims
%
% OUTPUT ARGUMENTS
%   ctrlPos         position of the controls
%   sheetDims       total sheetDims of all controls ([width height])
%-------------------------------------------------------------------------------
function [sheetDims,ctrlPos] = FcnOptionsCtrlPositions(commonGeom)

strings_and_styles = {...
    'Include in generated file ',                     'radiobutton'; ...
    'Compile & link to production code application ', 'radiobutton'; ...
    'System headerfile ',                             'checkbox',; ...
    'Code file: ',                                    'text'; ...
    '',                                               'edit'; ...
    '  . . .  ',                                      'pushbutton'; ...
    'Visible in subsystems below current level ',     'checkbox'};

[...
    includeRadioButtonSize, ...
    complinkRadioButtonSize, ...
    systemheaderCheckBoxSize, ...
    filenameLabelSize, ...
    filenameEditSize, ...
    browseButtonSize, ...
    visibleCheckboxSize] = ...
    ds_get_uicontrol_sizes(commonGeom,strings_and_styles);

widths = ...
    [filenameLabelSize(1)
    complinkRadioButtonSize(1)
    browseButtonSize(1)];

[col,colWidth,colDelta,rowDelta] = ds_get_gui_columns(widths,commonGeom);
% correct filenameEditSize
filenameEditSize(1) = complinkRadioButtonSize(1);

% correct col positions, because no panel used
col = col + commonGeom.frameSideEdgeBuffer;

cx = col(2);
cy = commonGeom.bottomSheetOffset + ...
    commonGeom.sheetBottomEdgeBuffer;
ctrlPos.visibleCheckBox = ...
    [cx cy visibleCheckboxSize];
cy = cy + commonGeom.textHeight + rowDelta;
ctrlPos.systemheaderCheckBox = ...
    [cx cy systemheaderCheckBoxSize];
cy = cy + commonGeom.editHeight + rowDelta;
ctrlPos.includeRadioButton = ...
    [cx cy includeRadioButtonSize];
cy = cy + commonGeom.textHeight + rowDelta;
ctrlPos.complinkRadioButton = ...
    [cx cy complinkRadioButtonSize];

% file info object
cx = col(1);
cy = cy + commonGeom.editHeight + rowDelta;
ctrlPos.fileinfoLabel = ...
    [cx cy filenameLabelSize];
cx = col(2);
ctrlPos.fileinfoEdit = ...
    [cx cy filenameEditSize];
cx = col(3);
ctrlPos.fileinfoBrowseButton = ...
    [cx cy browseButtonSize];

% code file
cx = col(1);
cy = cy + commonGeom.editHeight + rowDelta;
ctrlPos.filenameLabel = ...
    [cx cy filenameLabelSize];
cx = col(2);
ctrlPos.filenameEdit = ...
    [cx cy filenameEditSize];
cx = col(3);
ctrlPos.browseButton = ...
    [cx cy browseButtonSize];

width = ...
    sum(colWidth)+ colDelta + ...
    2*commonGeom.sheetSideEdgeBuffer + ...
    commonGeom.frameSideEdgeBuffer;
height = ...
    commonGeom.sheetTopEdgeBuffer + ...
    4 * commonGeom.editHeight  + ...
    2 * commonGeom.textHeight + ...
    7 * rowDelta + ...
    commonGeom.sheetBottomEdgeBuffer;

sheetDims = [width height];


%-------------------------------------------------------------------------------
% FcnCreateOptionsPage creates option page. Edit fields and checkboxes are left
%   empty, they are filled out with the block data in the update function
%
% INPUT ARGUMENTS
%   pageNum     number of the page
%   dlgfig      handle of dialog figure
%   dlgdata     dialog data
%
% OUTPUT ARGUMENTS
%   dlgdata     dialog data
%-------------------------------------------------------------------------------
function dlgdata = FcnCreateOptionsPage(pageNum,dlgfig,dlgdata)

data = dlgdata.data;
ctrlPos = dlgdata.pageData{pageNum}.ctrlPos;

if dlgdata.bIsFullVs
    whiteColor = 'w';
    EnableOn = 'on';
else
    whiteColor = get(dlgfig,'Color');
    EnableOn = 'inactive';
end

Children.filenameLabel = uicontrol( ...
    'Parent',             dlgfig, ...
    'String',             'Code file:', ...
    'Style',              'text', ...
    'Position',           ctrlPos.filenameLabel);

Children.filenameEdit = uicontrol( ...
    'Parent',             dlgfig, ...
    'String',             data.codefile, ...
    'BackGroundColor',    whiteColor, ...
    'Enable',             EnableOn, ...
    'Style',              'edit', ...
    'Position',           ctrlPos.filenameEdit);

% browse button
Children.browseButton = uicontrol( ...
    'Parent', dlgfig, ...
    'Enable', flag2str(dlgdata.bIsFullVs), ...
    'Style', 'pushbutton', ...
    'String','  . . .  ', ...
    'Position',ctrlPos.browseButton);

Children.fileinfoLabel = uicontrol( ...
    'Parent',             dlgfig, ...
    'String',             'File info:', ...
    'Style',              'text', ...
    'Position',           ctrlPos.fileinfoLabel);

Children.fileinfoEdit = uicontrol( ...
    'Parent',             dlgfig, ...
    'String',             ' ', ...
    'BackGroundColor',    whiteColor, ...
    'Enable',             EnableOn, ...
    'Style',              'edit', ...
    'Position',           ctrlPos.fileinfoEdit);

% browse button
Children.fileinfoBrowseButton = uicontrol( ...
    'Parent', dlgfig, ...
    'Enable', flag2str(dlgdata.bIsFullVs), ...
    'Style', 'pushbutton', ...
    'String','  . . .  ', ...
    'Position',ctrlPos.fileinfoBrowseButton);

fileinfoCMenu = uicontextmenu('Parent', dlgfig);
set(Children.fileinfoEdit, 'UIContextMenu', fileinfoCMenu);
pageName = dlgdata.pageNames{pageNum};
menu.select = uimenu(fileinfoCMenu, ...
    'Label', 'Select', ...
    'Callback', sprintf('tldlg(''%s'',gcbf,''fileinfoBrowseButton'')',pageName));
menu.show = uimenu(fileinfoCMenu, ...
    'Label', 'Show in DD Manager', ...
    'Callback', sprintf('tldlg(''%s'',gcbf,''fileinfoShowDDObject'')',pageName), ...
    'Separator','on');
set(fileinfoCMenu, 'UserData', menu);

% include and compile & link radiobuttons
Children.includeRadioButton  = uicontrol( ...
    'Parent',             dlgfig, ...
    'Enable',             flag2str(dlgdata.bIsFullVs & ~isempty(data.codefile)), ...
    'Style',              'radiobutton', ...
    'Value',              (data.addfilemode==1 | data.addfilemode==3), ...
    'String',             'Include in generated file', ...
    'Position',           ctrlPos.includeRadioButton );

Children.complinkRadioButton  = uicontrol( ...
    'Parent',             dlgfig, ...
    'Enable',             flag2str(dlgdata.bIsFullVs & ~isempty(data.codefile)), ...
    'Style',              'radiobutton', ...
    'Value',              (data.addfilemode==2), ...
    'String',             'Compile & link to production code application', ...
    'Position',           ctrlPos.complinkRadioButton );

Children.systemheaderCheckBox = uicontrol( ...
    'Parent',             dlgfig, ...
    'Enable',             flag2str(dlgdata.bIsFullVs & ~isempty(data.codefile) & (data.addfilemode ~= 2)), ...
    'Style',              'checkbox', ...
    'Value',              (data.addfilemode==3), ...
    'String',             'System headerfile', ...
    'Position',           ctrlPos.systemheaderCheckBox );

Children.visibleCheckbox = uicontrol( ...
    'Parent',             dlgfig, ...
    'Enable',             flag2str(dlgdata.bIsFullVs & ~isempty(data.codefile) & (data.addfilemode ~= 2)), ...
    'Style',              'checkbox', ...
    'Value',              data.visible, ...
    'String',             'Visible in subsystems below current level', ...
    'Position',           ctrlPos.visibleCheckBox );

dlgdata.pageData{pageNum}.children = Children;


%-------------------------------------------------------------------------------
% FcnManageOptionsPage manages option page.
%
% INPUT ARGUMENTS
%   pageNum     number of the page
%   dlgdata     dialog data
%   action      depending on the field that has been edited
%
% OUTPUT ARGUMENTS
%   dlgdata     dialog data
%   bModified   flag = 1, if data has been modified, =0 otherwise
%-------------------------------------------------------------------------------
function [dlgdata, bModified] = FcnManageOptionsPage(pageNum, dlgdata, action)

bModified = 0;
Children = dlgdata.pageData{pageNum}.children;
data = dlgdata.data;
radiobuttons = [Children.includeRadioButton Children.complinkRadioButton];

switch action
    case 'filenameEdit'
        filename = deblank(get(Children.filenameEdit,'String'));
        bModified = true;
        if ~isempty(filename) && ~all(isspace(filename))
            while filename(1) == ' '
                filename = filename(2:end);
            end
            data.codefile = filename;
        else
            fprintf('');
        end

    case 'systemheaderCheckBox'
        if get(Children.systemheaderCheckBox,'Value')
            data.addfilemode = 3;
        else
            data.addfilemode = 1;
        end
        bModified = true;

    case {'includeRadioButton','complinkRadioButton'}
        pressedButton = Children.(action);
        ds_handle_radiobuttons(radiobuttons,pressedButton);
        link = find(radiobuttons == pressedButton);
        if ~(link == 1 && data.addfilemode == 3), 
            data.addfilemode = link; 
        end
        bModified = true;

    case 'visibleCheckbox'
        data.visible = get(Children.visibleCheckbox,'Value');
        bModified = true;

    case 'browseButton'
        if data.addfilemode == 1
            filterstr = '*.h';
            caption = 'Header Files';
        else
            filterstr = '*.c';
            caption = 'C Sourcecode Files';
        end
        [filename,pathname] = uigetfile(filterstr,caption);
        if ischar(filename)
            if data.addfilemode == 2 && ~strcmpi(pathname,[pwd filesep])
                data.codefile = fullfile(pathname,filename);
            else
                data.codefile = filename;
            end
            set(Children.filenameEdit,'String',data.codefile);
            bModified = true;
        end

    case 'fileinfoBrowseButton'
        % Browse button: Get new FileSpecification from reference selection dialog
        data.fileinfo = dsdd( 'SelectObject', ...
            'entryPath',       '/Pool/Modules', ...
            'CurrentPath',     data.fileinfo, ...
            'ObjectKind',      'FileSpecification');
        bModified = true;

    case 'fileinfoEdit'
        % Edit field: Get new module from edit field
        data.fileinfo = tl_deblank(get(Children.fileinfoEdit,'String'),2);
        bModified = true;

    case 'fileinfoShowDDObject'
        selectedModule = data.fileinfo;
        if isempty(selectedModule)
            % jump to node in DD Manager
            dsddman('Select', '/Pool/Modules');
        else
            % jump to function object in DD Manager
            modulePath = ['/Pool/Modules/' selectedModule];
            dsddman('Select', modulePath);
        end

    otherwise
        error(['Invalid control ' action]);

end % switch(action)
dlgdata.data = data;


%-------------------------------------------------------------------------------
% FUNCTION DESCRIPTION
%   FcnUpdateOptionsPage(dlgfig,dlgdata,pageNum)
%   Function to to update controls on options page: Enable/disable controls,
%   write data to edit fields, highlight invalid/inconsistent data.
%   Function is called after FcnCreateOptionsPage and by FcnManageOptionsPage in
%   case the dialog has to be updated due to new data
%
% INPUT ARGUMENTS
%   pageNum     Number of page
%   dlgfig      Handle of dialog figure
%   dlgdata     dialog data
%
% OUTPUT ARGUMENTS
%   dlgdata     dialog data
%-------------------------------------------------------------------------------
function dlgdata = FcnUpdateOptionsPage(pageNum,dlgfig,dlgdata) %#ok<INUSL>

data = dlgdata.data;
Children = dlgdata.pageData{pageNum}.children;
data = tl_sync_dd_blockdata(data, 'BlockType', dlgdata.maskType);

DefColor  = get(dlgfig,'Color');

IsFullVsON = flag2str(dlgdata.bIsFullVs);

fileinfoColor = 'k';
% fileinfo object
fileinfo = data.fileinfo;
if ~isempty(fileinfo) && dsdd('exist', ['/Pool/Modules/' fileinfo])
    codefileEnable = 'inactive';
    codefileBgColor = DefColor;
    bFileExist = true;
    systemheaderEnable = 'off';
    radiobuttonsEnable = 'off';
else
    codefileBgColor = 'w';
    if ~isempty(fileinfo)
        fileinfoColor = 'r';
    end
    codefileEnable = IsFullVsON;
    bFileEmpty = isempty(data.codefile);
    bFileExist = ~bFileEmpty && (exist(data.codefile, 'file') || strcmp(data.codefile, 'untitled.c'));
    systemheaderEnable = flag2str(dlgdata.bIsFullVs && ~bFileEmpty && data.addfilemode ~= 2);
    radiobuttonsEnable = flag2str(dlgdata.bIsFullVs && ~bFileEmpty);
end

set(Children.complinkRadioButton, ...
    'Enable', radiobuttonsEnable, ...
    'Value', data.addfilemode==2);
set(Children.includeRadioButton, ...
    'Enable', radiobuttonsEnable, ...
    'Value', data.addfilemode==1 || data.addfilemode==3);

set(Children.visibleCheckbox, ...
    'Enable', flag2str(dlgdata.bIsFullVs && bFileExist && data.addfilemode ~= 2), ...
    'Value', data.visible);
set(Children.systemheaderCheckBox, ...
    'Enable', systemheaderEnable, ...
    'Value', data.addfilemode==3);

% Codefile and CodeEdit button
userDataEditCode = get(dlgdata.SystemButtons.EditCode, 'UserData');
if bFileExist || isempty(data.codefile)
    set(dlgdata.SystemButtons.EditCode, ...
        'CData',  userDataEditCode.cDataEnabled, ...
        'Enable', 'on');
    codefileColor = 'k';
else
    set(dlgdata.SystemButtons.EditCode, ...
        'CData',  userDataEditCode.cDataDisabled, ...
        'Enable', 'off');
    codefileColor = 'r';
end

% Set all fields which do not depend on other fields...
set(Children.filenameEdit, ...
    'String',           data.codefile, ...
    'BackGroundColor',  codefileBgColor, ...
    'Foregroundcolor',  codefileColor, ...
    'Enable',           codefileEnable);
set(Children.browseButton, ...
    'Enable',           flag2str(strcmp(codefileEnable, 'on')));
set(Children.fileinfoEdit, ...
    'String',           data.fileinfo, ...
    'BackGroundColor',  'w', ...
    'Foregroundcolor',  fileinfoColor, ...
    'Enable',           IsFullVsON);

% set status of context menu controls:
moduleCMenu = get(Children.fileinfoEdit, 'UIContextMenu');
moduleMenu  = get(moduleCMenu, 'UserData');
set(moduleMenu.select, 'Enable', IsFullVsON);
set(moduleMenu.show,   'Enable', flag2str(dlgdata.bDSDDMan));

dlgdata.data = data;
% end of function FcnUpdateOptionsPage
